//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "aura.h"
#include "wince.h"
#include "private.h"

typedef struct _EventDescr {
    HANDLE m_hEvent;
    BOOL   m_bManualReset;
    DWORD  m_eventState;
}EventDescr;

AURA_API AuraEvent_Create(
        /* [in] */ Aura_Bool bManualReset,
        /* [in] */ Aura_EventState initialState,
        /* [out] */ Aura_Handle  * phEvent)
{
    EventDescr * pDescr = NULL;
    HANDLE       hEvent = NULL;
    Aura_ECode  ec = AURA_NOERROR;

    assert(NULL != phEvent);

    pDescr = (EventDescr *)Aura_malloc(sizeof(*pDescr));
    if (NULL == pDescr) {
        ec = AURA_E_OUT_OF_MEMORY;
        goto E_FAIL_EXIT;
    }

    hEvent = CreateEventW(NULL,
                    (BOOL)bManualReset,
                    (BOOL)!!initialState,
                    NULL);
    if (NULL == hEvent) {
        ec = GetLastAuraECode();
        goto E_FAIL_EXIT;
    }

    pDescr->m_hEvent = hEvent;
    pDescr->m_bManualReset = (BOOL)bManualReset;
    pDescr->m_eventState = (DWORD)initialState;

    *phEvent = (EventDescr *)pDescr;

    return AURA_NOERROR;

E_FAIL_EXIT:
    if (NULL != pDescr) {
        Aura_free(pDescr);
    }
    return ec;
}

AURA_API AuraEvent_Wait(
        /* [in] */ Aura_Handle hEvent,
        /* [in] */ Aura_Millisecond32 timeOut,
        /* [out] */ Aura_WaitResult * pResult,
        /* [out] */ Aura_EventState * pState)
{
    EventDescr * pDescr = (EventDescr *)hEvent;
    DWORD dwRes = 0;

    assert(NULL != pDescr);
    assert(NULL != pResult);
    assert(NULL != pState);

    dwRes = WaitForSingleObject(pDescr->m_hEvent, (DWORD)timeOut);
    if (WAIT_FAILED == dwRes) {
        goto E_FAIL_EXIT;
    }
    else if (WAIT_OBJECT_0 == dwRes) {
        *pResult = Aura_WaitResult_OK;
        *pState  = (Aura_EventState)pDescr->m_eventState;
    }
    else if (WAIT_TIMEOUT == dwRes) {
        *pResult = Aura_WaitResult_TimedOut;
    }
#if _DEBUG
    else {
        assert(0);
    }
#endif

    return AURA_NOERROR;

E_FAIL_EXIT:
    return GetLastAuraECode();
}

AURA_API AuraEvent_Signal(
        /* [in] */ Aura_Handle hEvent,
        /* [in] */ Aura_EventState state)
{
    EventDescr * pDescr = (EventDescr *)hEvent;
    BOOL bSuccess = FALSE;

    assert(NULL != pDescr);

    pDescr->m_eventState = state;
    bSuccess = SetEvent(pDescr->m_hEvent);
    if (!bSuccess) {
        goto E_FAIL_EXIT;
    }

    return AURA_NOERROR;

E_FAIL_EXIT:
    return GetLastAuraECode();
}

AURA_API AuraEvent_Unsignal(
        /* [in] */ Aura_Handle hEvent)
{
    EventDescr * pDescr = (EventDescr *)hEvent;
    BOOL bSuccess = FALSE;

    assert(NULL != pDescr);

    pDescr->m_eventState = AURA_UNSIGNALED;
    bSuccess = ResetEvent(pDescr->m_hEvent);
    if (!bSuccess) {
        goto E_FAIL_EXIT;
    }

    return AURA_NOERROR;
E_FAIL_EXIT:
    return GetLastAuraECode();
}

AURA_API AuraEvent_Destroy(
        /* [in] */ Aura_Handle hEvent)
{
    EventDescr * pDescr = (EventDescr *)hEvent;
    BOOL bSuccess = FALSE;

    assert(NULL != pDescr);

    CloseHandle(pDescr->m_hEvent);
    Aura_free(pDescr);

    return AURA_NOERROR;
}

